<template>
  <div class="stress-test-container">
    <el-card class="config-card">
      <template #header>
        <div class="card-header">
          <h2>压力测试配置</h2>
        </div>
      </template>
      
      <el-form :model="testConfig" label-width="120px">
        <el-form-item label="目标地址">
          <el-input v-model="testConfig.target" placeholder="请输入要测试的网站URL或IP地址" />
          <div v-if="resolvedIP && !isIP" class="resolved-ip">
            解析到的IP地址: {{ resolvedIP }}
          </div>
        </el-form-item>
        
        <el-form-item label="测试模式">
          <el-radio-group v-model="testConfig.mode">
            <el-radio label="normal">普通压测</el-radio>
            <el-radio label="dos">DOS压测</el-radio>
          </el-radio-group>
        </el-form-item>
        
        <el-form-item label="并发用户数">
          <el-slider v-model="testConfig.concurrentUsers" :min="10" :max="10000" />
        </el-form-item>
        
        <el-form-item label="测试时长(秒)">
          <el-input-number v-model="testConfig.duration" :min="10" :max="360000" />
        </el-form-item>
        
        <el-form-item>
          <el-button type="primary" @click="handleStartTest" :loading="testStore.isTesting">
            开始测试
          </el-button>
          <el-button @click="handleStopTest" :disabled="!testStore.isTesting">
            停止测试
          </el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <el-card class="monitor-card" v-if="testStore.currentTest">
      <template #header>
        <div class="card-header">
          <h2>实时监控</h2>
          <el-tag :type="testStore.isTesting ? 'success' : 'info'">
            {{ testStore.isTesting ? '测试进行中' : '测试已完成' }}
          </el-tag>
        </div>
      </template>
      
      <div class="monitor-grid">
        <div class="monitor-item">
          <h3>总请求数</h3>
          <div class="value">{{ testStore.currentTest?.totalRequests || 0 }}</div>
        </div>
        <div class="monitor-item">
          <h3>成功请求</h3>
          <div class="value success">{{ testStore.currentTest?.successRequests || 0 }}</div>
        </div>
        <div class="monitor-item">
          <h3>失败请求</h3>
          <div class="value error">{{ testStore.currentTest?.failedRequests || 0 }}</div>
        </div>
        <div class="monitor-item">
          <h3>平均响应时间</h3>
          <div class="value">{{ testStore.currentTest?.avgResponseTime || 0 }}ms</div>
        </div>
        <div class="monitor-item">
          <h3>每秒请求数</h3>
          <div class="value warning">{{ testStore.currentTest?.apiStats?.[0]?.requestsPerSecond || 0 }}</div>
        </div>
      </div>
      
      <div class="status-codes" v-if="testStore.currentTest?.statusCodes">
        <h3>HTTP状态码统计</h3>
        <el-row :gutter="20">
          <el-col :span="6" v-for="(count, code) in testStore.currentTest.statusCodes" :key="code">
            <div class="status-code-item" :class="getStatusCodeClass(code)">
              <span class="code">{{ code }}</span>
              <span class="count">{{ count }}</span>
            </div>
          </el-col>
        </el-row>
      </div>
      
      <div class="chart-container">
        <div ref="requestChart" style="width: 100%; height: 300px;"></div>
      </div>

      <div class="response-details" v-if="testStore.currentTest?.apiStats?.[0]?.lastResponse">
        <h3>最后一次响应详情</h3>
        <el-descriptions border>
          <el-descriptions-item label="状态码">
            {{ testStore.currentTest.apiStats[0].lastResponse.statusCode }}
            ({{ testStore.currentTest.apiStats[0].lastResponse.statusText }})
          </el-descriptions-item>
          <el-descriptions-item label="响应数据">
            <div class="response-data">
              {{ testStore.currentTest.apiStats[0].lastResponse.responseData || '无数据' }}
            </div>
          </el-descriptions-item>
          <el-descriptions-item label="错误信息" v-if="testStore.currentTest.apiStats[0].lastResponse.error">
            {{ testStore.currentTest.apiStats[0].lastResponse.error }}
            ({{ testStore.currentTest.apiStats[0].lastResponse.errorType }})
          </el-descriptions-item>
        </el-descriptions>
      </div>

      <div class="api-list" v-if="testStore.currentTest?.apiStats?.length">
        <h3>接口监控</h3>
        <el-table :data="testStore.currentTest.apiStats" style="width: 100%">
          <el-table-column prop="endpoint" label="接口" />
          <el-table-column prop="totalRequests" label="请求数" width="100" />
          <el-table-column prop="successRequests" label="成功数" width="100" />
          <el-table-column prop="failedRequests" label="失败数" width="100" />
          <el-table-column prop="avgResponseTime" label="平均响应时间" width="120">
            <template #default="scope">
              {{ scope.row.avgResponseTime }}ms
            </template>
          </el-table-column>
        </el-table>
      </div>
    </el-card>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, onUnmounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useTestStore } from '../stores/test'
import { ElMessage } from 'element-plus'
import * as echarts from 'echarts'
import { resolveHostname, isValidIP } from '../utils/dns'

const router = useRouter()
const testStore = useTestStore()
const requestChart = ref(null)
let chart = null
const resolvedIP = ref('')
const isIP = ref(false)

const testConfig = reactive({
  target: '',
  mode: 'normal',
  concurrentUsers: 10,
  duration: 60
})

// Watch for changes in the target input
watch(() => testConfig.target, async (newValue) => {
  if (!newValue) {
    resolvedIP.value = ''
    isIP.value = false
    return
  }
  
  isIP.value = isValidIP(newValue)
  if (!isIP.value) {
    try {
      resolvedIP.value = await resolveHostname(newValue)
    } catch (error) {
      resolvedIP.value = ''
      ElMessage.warning('无法解析域名的IP地址')
    }
  } else {
    resolvedIP.value = ''
  }
})

const handleStartTest = async () => {
  if (!testConfig.target) {
    ElMessage.error('请输入目标网站URL或IP地址')
    return
  }
  
  try {
    const config = {
      ...testConfig,
      url: testConfig.target,
      ip: isIP.value ? testConfig.target : resolvedIP.value
    }
    await testStore.startTest(config)
    initChart()
  } catch (error) {
    ElMessage.error('开始测试失败: ' + error.message)
  }
}

const handleStopTest = async () => {
  await testStore.stopTest()
  router.push('/history')
}

const initChart = () => {
  if (chart) {
    chart.dispose()
  }
  
  chart = echarts.init(requestChart.value)
  const option = {
    title: {
      text: '响应时间趋势'
    },
    tooltip: {
      trigger: 'axis'
    },
    xAxis: {
      type: 'time',
      splitLine: {
        show: false
      }
    },
    yAxis: {
      type: 'value',
      name: '响应时间(ms)',
      splitLine: {
        lineStyle: {
          type: 'dashed'
        }
      }
    },
    series: [{
      name: '响应时间',
      type: 'line',
      smooth: true,
      data: []
    }]
  }
  
  chart.setOption(option)
}

// 监听测试数据变化，更新图表
watch(
  () => testStore.currentTest?.apiStats,
  (apiStats) => {
    if (chart && apiStats?.length) {
      const latestStats = apiStats[0]
      if (latestStats.responseTimes?.length) {
        chart.setOption({
          series: [{
            data: latestStats.responseTimes.map(item => [item.time, item.value])
          }]
        })
      }
    }
  },
  { deep: true }
)

const getStatusCodeClass = (code) => {
  const codeNum = parseInt(code);
  if (codeNum >= 200 && codeNum < 300) return 'status-success';
  if (codeNum >= 300 && codeNum < 400) return 'status-redirect';
  if (codeNum >= 400 && codeNum < 500) return 'status-client-error';
  if (codeNum >= 500) return 'status-server-error';
  return '';
}

onMounted(() => {
  window.addEventListener('resize', () => {
    chart?.resize()
  })
})

onUnmounted(() => {
  testStore.stopTest()
  chart?.dispose()
  window.removeEventListener('resize', () => {
    chart?.resize()
  })
})
</script>

<style scoped>
.stress-test-container {
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}

.config-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.monitor-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  margin-bottom: 20px;
}

.monitor-item {
  text-align: center;
  padding: 20px;
  background: #f5f7fa;
  border-radius: 8px;
}

.monitor-item h3 {
  margin: 0 0 10px 0;
  color: #606266;
}

.value {
  font-size: 24px;
  font-weight: bold;
  color: #409EFF;
}

.value.success {
  color: #67C23A;
}

.value.error {
  color: #F56C6C;
}

.value.warning {
  color: #E6A23C;
}

.chart-container {
  margin: 20px 0;
}

.api-list {
  margin-top: 20px;
}

.api-list h3 {
  margin-bottom: 20px;
}

.resolved-ip {
  margin-top: 8px;
  font-size: 14px;
  color: #409EFF;
}

.status-codes {
  margin: 20px 0;
  padding: 20px;
  background: #f5f7fa;
  border-radius: 8px;
}

.status-code-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  margin-bottom: 10px;
  border-radius: 4px;
  background: white;
}

.status-code-item .code {
  font-weight: bold;
}

.status-code-item .count {
  background: #409EFF;
  color: white;
  padding: 2px 8px;
  border-radius: 10px;
}

.status-success {
  border-left: 4px solid #67C23A;
}

.status-redirect {
  border-left: 4px solid #E6A23C;
}

.status-client-error {
  border-left: 4px solid #F56C6C;
}

.status-server-error {
  border-left: 4px solid #909399;
}

.response-details {
  margin: 20px 0;
  padding: 20px;
  background: #f5f7fa;
  border-radius: 8px;
}

.response-data {
  max-height: 200px;
  overflow-y: auto;
  padding: 10px;
  background: #f8f9fa;
  border-radius: 4px;
  font-family: monospace;
  white-space: pre-wrap;
}
</style> 